home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 301-325 / disk_319 / cnewssrc / cnews.src.lzh / libbig / active_fast.c next >
C/C++ Source or Header  |  1989-12-29  |  5KB  |  198 lines

  1. /*
  2.  * active file access functions (big, fast, in-memory version)
  3.  */
  4.  
  5. #ifdef DEBUG
  6. #  define STAT(x)    {    fprintf(stderr,"%s: %d, ",__FUNC__,__LINE__);\
  7.                         fprintf x;\
  8.                         fflush(stderr); }
  9. #else
  10. #  define STAT(x)
  11. #endif
  12.  
  13. #include <stdio.h>
  14.  
  15. #ifndef AMIGA
  16. #  include <sys/types.h>
  17. #  include <sys/stat.h>
  18. #else
  19. #  include <libraries/dos.h>
  20. #endif /* AMIGA */
  21.  
  22. #include "libc.h"
  23. #include "news.h"
  24. #include "config.h"
  25. #include "active.h"
  26.  
  27. /* private */
  28. static char *active = NULL;    /* cache: points at entire active file */
  29. static int actsize;            /* bytes in active: type int fixed by fread */
  30. static char **actlnps;        /* point at lines in active file */
  31. static unsigned actlines;    /* lines in actlnps actually used */
  32.  
  33. /* imports from active.c */
  34. extern char actrelnm[];
  35.  
  36. /* forwards */
  37. FORWARD statust actmkindx();
  38.  
  39. statust actfload(fp)
  40. FILE *fp;
  41. {
  42.     statust status = ST_OKAY;
  43.  
  44.     if (fp != NULL && active == NULL) {
  45. #ifndef AMIGA
  46.         struct stat sb;
  47.  
  48.         errno = 0;
  49.         if (fstat(fileno(fp), &sb) < 0)
  50.             warning("can't fstat `%s'", ctlfile(actrelnm));
  51.         else if (actsize = sb.st_size, /* squeeze into an int */
  52.             (unsigned)actsize != sb.st_size)
  53.             warning("`%s' won't fit into memory", ctlfile(actrelnm));
  54.         else
  55. #else /* AMIGA */
  56.         struct FileInfoBlock fib;
  57.         struct FileLock *lock, *Lock();
  58.         char *active_file;
  59.  
  60.         active_file = ctlfile(actrelnm);
  61.         STAT((stderr, "creating cache for '%s'\n", active_file));
  62.         if (lock = Lock(active_file, ACCESS_READ)) {
  63.             STAT((stderr, "Examine(0x%06lx, 0x%06lx)\n", lock, &fib));
  64.             Examine(lock, &fib);
  65.             UnLock(lock);
  66.             actsize = fib.fib_Size;        /* Squeeze into an integer */
  67.             if ((unsigned) actsize != fib.fib_Size) {
  68.                 STAT((stderr, "about to issue size warning\n"));
  69.                 warning("`%s' won't fit into memory", ctlfile(actrelnm));
  70.             }
  71.         } else {
  72.             STAT((stderr, "lock denied!\n"));
  73.         }
  74. #endif /* AMIGA */
  75.         STAT((stderr, "about to allocate %d bytes for cache\n", actsize+1));
  76.         if ((active = malloc((unsigned)actsize+1)) == NULL)
  77.             warning("can't allocate memory for `%s'", ctlfile(actrelnm));
  78.         else {
  79.             rewind(fp);
  80.             /*
  81.              * If we read with fgetms, we might be able to avoid
  82.              * calling linescan().
  83.              */
  84.             STAT((stderr, "cache being read...\n"));
  85.             if (fread(active, 1, actsize, fp) != actsize) {
  86.                 warning("error reading `%s'", ctlfile(actrelnm));
  87.                 status |= ST_DROPPED;
  88.             } else {
  89.                 STAT((stderr, "calling actmkindx()\n"));
  90.                 status |= actmkindx();
  91.             }
  92.         }
  93.         if (active == NULL)
  94.             status |= ST_DROPPED;    /* give up! */
  95.         if (status != ST_OKAY) {
  96.             nnfree(&active);
  97.             nnafree(&actlnps);
  98.         }
  99.     }
  100.     return status;
  101. }
  102.  
  103. static statust actmkindx()            /* build actlnps index for active */
  104. {
  105.     register statust status = ST_OKAY;
  106.     unsigned lnpsz;
  107.     int maxlines;
  108.  
  109.     active[actsize] = '\0';        /* make a proper string */
  110.     /* +1 for a possible partial line +1 for a dummy to check overflow */
  111.  
  112.     STAT((stderr, "about to count lines...\n"));
  113.     maxlines = charcount(active, '\n') + 2;
  114.     lnpsz = sizeof(char *) * (long) maxlines;
  115.  
  116.     STAT((stderr, "%u lines; array size %lu\n",
  117.         maxlines, (long) maxlines * sizeof(char *)));
  118.  
  119.     if (lnpsz != sizeof(char *) * (long)maxlines ||
  120.                 (actlnps = (char **)malloc(lnpsz)) == NULL) {
  121.         STAT((stderr, "warning:  index won't fit in memory\n"));
  122.         warning("`%s' index won't fit in memory", ctlfile(actrelnm));
  123.         status |= ST_DROPPED;
  124.     } else {
  125.         actlnps[maxlines - 2] = "";    /* in case no partial line */
  126.         actlnps[maxlines - 1] = "";    /* end sentinel */
  127.         actlines = linescan(active, actlnps, maxlines);
  128.         if (actlines >= maxlines) {
  129.             (void) fprintf(stderr,
  130.                 "%s: too many newsgroups in `%s' (can't happen)\n",
  131.                 progname, ctlfile(actrelnm));
  132.             status |= ST_DROPPED;
  133.         }
  134.     }
  135.     return status;
  136. }
  137.  
  138. /*
  139.  * Store in lnarray the addresses of the starts of lines in s.
  140.  * Return the number of lines found; if greater than nent,
  141.  * store only nent and return nent.
  142.  * Thus lnarray should be one bigger than needed to detect overflow.
  143.  */
  144.  
  145. int linescan(s, lnarray, nent)
  146. char *s;
  147. char **lnarray;
  148. register int nent;
  149. {
  150.     register char **lnarrp = lnarray;
  151.     register int i = 0;
  152.     register char *nlp = s;
  153.  
  154.     if (i < nent)
  155.         *lnarrp++ = nlp;
  156.     while (++i < nent && (nlp = index(nlp, '\n')) != NULL && *++nlp != '\0')
  157.         *lnarrp++ = nlp;
  158.     return i;        /* number of addrs stored */
  159. }
  160.  
  161. statust actfsync(fp)            /* write to disk, fp is open */
  162. FILE *fp;
  163. {
  164.     statust status = ST_OKAY;
  165.  
  166.     rewind(fp);
  167.     if (active != NULL) {
  168.         if (fwrite(active, actsize, 1, fp) != 1)
  169.             status |= ST_DROPPED;    /* serious loss */
  170.         nnfree(&active);
  171.         nnafree(&actlnps);
  172.     }
  173.     return status;
  174. }
  175.  
  176. /* ARGSUSED fp */
  177. char *actfind(fp, ng, nglen)
  178. FILE *fp;
  179. register char *ng;
  180. register int nglen;
  181. {
  182.     register char *pos;
  183.     register unsigned line = 0;
  184.  
  185.     while (pos = actlnps[line], line++ < actlines && pos[0] != '\0')
  186.         if (STREQN(pos, ng, nglen) && pos[nglen] == ' ')
  187.             return pos;
  188.     return NULL;
  189. }
  190.  
  191. /* ARGSUSED */
  192. statust actfwrnum(fp, pos)
  193. FILE *fp;
  194. char *pos;
  195. {
  196.     return ST_OKAY;
  197. }
  198.